﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Birkelund.QueryStrings.Internals;
using NUnit.Framework;

namespace Birkelund.QueryStrings.Test
{
    public class CommonTest
    {
        [Test]
        [ExpectedException(typeof(NullReferenceException))]
        public void CurrentUrlTest()
        {
            Uri currentUrl = Common.CurrentUrl;
        }

        #region Cast
        [Test]
        public void CastTest_Bool()
        {
            Assert.AreEqual(true, Common.Cast<bool>("True"));
        }

        [Test]
        public void CastTest_Int()
        {
            Assert.AreEqual(1234, Common.Cast<int>("1234"));
        }

        [Test]
        [SetCulture("da-DK")]
        public void CastTest_Double_DK()
        {
            Assert.AreEqual(12.34, Common.Cast<double>("12,34"));
        }

        [Test]
        [SetCulture("da-DK")]
        public void CastTest_Float_DK()
        {
            Assert.AreEqual(12.34F, Common.Cast<float>("12,34"));
        }

        [Test]
        [SetCulture("da-DK")]
        public void CastTest_Decimal_DK()
        {
            Assert.AreEqual(12.34M, Common.Cast<decimal>("12,34"));
        }

        [Test]
        [SetCulture("en-US")]
        public void CastTest_Double_US()
        {
            Assert.AreEqual(12.34, Common.Cast<double>("12.34"));
        }

        [Test]
        [SetCulture("en-US")]
        public void CastTest_Float_US()
        {
            Assert.AreEqual(12.34F, Common.Cast<float>("12.34"));
        }

        [Test]
        [SetCulture("en-US")]
        public void CastTest_Decimal_US()
        {
            Assert.AreEqual(12.34M, Common.Cast<decimal>("12.34"));
        }

        [Test]
        public void CastTest_DateTime()
        {
            Assert.AreEqual(new DateTime(2011, 12, 31, 23, 59, 59), Common.Cast<DateTime>("2011-12-31 23:59:59"));
        }

        [Test]
        public void CastTest_TimeStamp()
        {
            Assert.AreEqual(new TimeSpan(1, 23, 45), Common.Cast<TimeSpan>("1:23:45"));
        }

        [Test]
        public void CastTest_Guid()
        {
            Assert.AreEqual(new Guid("c1701aa2-dc25-4953-a7a6-3ee1b29e787d"), Common.Cast<Guid>("c1701aa2-dc25-4953-a7a6-3ee1b29e787d"));
        }

        [Test]
        public void CastTest_Enum()
        {
            Assert.AreEqual(DayOfWeek.Thursday, Common.Cast<DayOfWeek>("Thursday"));
        }
        #endregion

        #region ToTokenKeyValues
        [Test]
        public void ToTokenKeyValues_Positive()
        {
            NameValueCollection nvc = new NameValueCollection();
            nvc.Add("name1", "value1");
            nvc.Add("name2", "value2");
            nvc.Add("name3", "value3");

            IEnumerable<TokenKeyValue> tokens = nvc.ToTokenKeyValues();
            Assert.AreEqual(tokens.Count(), nvc.Count);
            Assert.AreEqual(tokens.Single(s => s.Key == "name1").Value, nvc["name1"]);
            Assert.AreEqual(tokens.Single(s => s.Key == "name2").Value, nvc["name2"]);
            Assert.AreEqual(tokens.Single(s => s.Key == "name3").Value, nvc["name3"]);
        }

        [Test]
        public void ToTokenKeyValues_Null()
        {
            NameValueCollection nvc = null;
            IEnumerable<TokenKeyValue> tokens = nvc.ToTokenKeyValues();
            Assert.IsNotNull(tokens);
            Assert.AreEqual(0, tokens.Count());
        }
        #endregion

        #region IsValidValueTypeToken
        [Test]
        public void IsValidValueTypeToken_PositiveTest(
            [Values(
                typeof(int),
                typeof(float),
                typeof(long),
                typeof(short),
                typeof(byte),
                typeof(double),
                typeof(bool),
                typeof(uint),
                typeof(ulong),
                typeof(ushort),
                typeof(sbyte),
                typeof(char),
                typeof(TimeSpan),
                typeof(Guid),
                typeof(DateTime),
                typeof(IntPtr),
                typeof(UIntPtr),
                typeof(TestEnum),
                typeof(TestFlagEnum))
            ] Type type)
        {
            bool isValid = Common.IsValidValueTypeToken(type);
            Assert.IsTrue(isValid, type.Name);
        }

        [Test]
        public void IsValidValueTypeToken_NegativeTest(
            [Values(
                typeof(int?),
                typeof(string),
                typeof(decimal), //decimal is not a primitive type
                typeof(StringBuilder),
                typeof(IEnumerable),
                typeof(IEnumerable<int>),
                typeof(List<byte>),
                typeof(List<byte?>),
                typeof(object),
                typeof(Exception),
                typeof(Type),
                typeof(Attribute))
            ] Type type)
        {
            bool isValid = Common.IsValidValueTypeToken(type);
            Assert.IsFalse(isValid, type.Name);
        }

        [Test]
        [ExpectedException(typeof(NullReferenceException))]
        public void IsValidValueTypeToken_NullTest()
        {
            bool isValid = Common.IsValidValueTypeToken(null);
        }
        #endregion

        [TestCase("qwerty_Ø", "QWERTY_ø", true, Result = false)]
        [TestCase("QWERTY_ø", "QWERTY_ø", true, Result = true)]
        [TestCase("qwerty_Ø", "qwerty_Ø", false, Result = true)]
        public bool AreEqual_UpperEqualsLower(string a, string b, bool isCaseSensitive)
        {
            bool areEqual = Common.AreEqual(a, b, isCaseSensitive);
            return areEqual;
        }
    }
}